import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.ListIterator;

/**
 * Generic object to represent a word phrase, using a list
 * as internal storage. List must be initialized to appropriate
 * implementation by subclasses
 * @author gabriel
 *
 */
public abstract class PhraseObject implements Comparable {

    /**
     * The list of words in a phrase, in order. Must be initialized
     * by subclass to appropriate implementation.
     */
    protected List wordList;
    
    /**
     * The list of line numbers that this phrase was found in the particular file 
     */
    protected LinkedList lineNumbers;

    /**
     * Copys a phrase into our list. It replaces any existing words
     * in our phrase list
     * @param phrase The phrase to copy
     */
    public void copyPhrase(PhraseObject phrase) {
        this.wordList.clear();
        ListIterator iter = phrase.getIterator();
        while (iter.hasNext()) {
            this.wordList.add(iter.next());
        }
        Iterator iterator = phrase.getLineNumberIterator();
        while (iterator.hasNext()) {
            this.lineNumbers.add(iterator.next());
        }
    }
    
    /**
     * Inserts a line number to its line number list
     * @param lineNumber
     */
    public void addLineNumber(int lineNumber)
    {
    	//This makes sure the list is not null

    	if(lineNumbers!=null)
    			lineNumbers.add(new Integer(lineNumber));
    }
    /**
     * Returns an iterator for the line number list
     * @return
     */
    public Iterator getLineNumberIterator()
    {
    	return lineNumbers.iterator();
    }
        
    /**
     * Returns a list iterator to iterate the list of words
     * @return a list iterator
     */
    public ListIterator getIterator() {
        return this.wordList.listIterator();
    }

    /**
     * gets the length of the phrase (number of words)
     * @return The lengths
     */
    public int getLength() {
        return this.wordList.size();
    }
    
    /**
     * Compares if two phrases, contained in a list, are equal
     * @param phrase The phrase to test us against 
     * @return if the phrase is equal
     */
    public boolean isPhraseEqual(PhraseObject phrase) {
        if (phrase.getLength() != this.wordList.size()) {
            return false;
        }
        ListIterator usIter = wordList.listIterator();
        ListIterator otherIter = phrase.getIterator();
        
        while (usIter.hasNext() && otherIter.hasNext()) {
            if (!(usIter.next().equals(otherIter.next()))) {
                return false;
            }
        }
        return true;
    }
    

    /**
     * 
     * @see java.lang.Object#equals(java.lang.Object)
     */
    public boolean equals(Object o) {
        if (o instanceof PhraseObject) {
            return this.isPhraseEqual((PhraseObject) o);
        }
        return false;
    }
    
    /**
     * The hashcode for this phrase, as determined by our list. For any phrase,
     * using the internal list object (any implementation), the hashcode will
     * be the same if the iteration of words in the phrase is the same.
     * @return The hashcode.
     */
    public int hashCode() {
        return this.wordList.hashCode();
    }
    
    /**
     * 
     * @param o The object to compare us to
     * @return negative, 0, or positive if we are less than, equal to
     *  or greater than the other object.
     */
    public int compareTo (Object o) {
        if (!(o instanceof PhraseObject)) {
            return -1;
        }
        PhraseObject phrase = (PhraseObject) o;
        ListIterator usIter = wordList.listIterator();
        ListIterator otherIter = phrase.getIterator();
        
        while (usIter.hasNext() && otherIter.hasNext()) {
            String us = (String) usIter.next();
            String other = (String) otherIter.next();
            int comp;
            if ((comp = us.compareTo(other)) != 0) {
                return comp;
            }
        }
        if (usIter.hasNext()) {
            return 1;
        }
        if (otherIter.hasNext()) {
            return -1;
        }
        return 0;
    }
    
    /**
     * 
     * @see java.lang.Object#toString()
     */
    public String toString() {
        /* Build a string representing a phrase */
        String ret = "";
        if (this.getLength() > 1) {
            ret += "<";
        }
        ListIterator iter = this.getIterator();
        if (iter.hasNext()) {
            ret += "\"" + iter.next() + "\"";
        }
        while(iter.hasNext()) {
            ret += ", \"" + iter.next() + "\"";
        }
        if (this.getLength() > 1) {
            ret += ">";
        }
        return ret;
    }
    
}
